package com.test.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.management.MBeanAttributeInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.util.List;
import java.util.Map;

/**
 * @ClassName SwaggerController
 * @Description
 * @Author Zhang Li Tao
 * @Date 2023/5/16 22:52
 * @Version 1.0
 **/
@RestController
@RequestMapping("collect")
@Api(value = "收集springboot对应jconsole指标")
@Slf4j
public class SwaggerController {
    @GetMapping("swagger")
    @ApiOperation(value = "获取所有回显", notes = "获取所有回显")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ip", value = "ip", dataType = "String", required = true),
            @ApiImplicitParam(name = "jmxPort", value = "jmxPort", dataType = "String", required = true, defaultValue = "8089"),
            @ApiImplicitParam(name = "tomcatPort", value = "tomcatPort", dataType = "String", required = true, defaultValue = "8080"),
    })
    public List<String> getAdbDescription(@RequestParam(value = "ip") String ip,
                                                 @RequestParam(value = "jmxPort") String jmxPort,
                                                 @RequestParam(value = "tomcatPort") String tomcatPort) throws Exception {
        List<String> resultList = CollUtil.newArrayList();


        List<String> objectList = CollUtil.newArrayList();

        objectList.add("Tomcat:type=Connector,port=" + tomcatPort);
        objectList.add("Tomcat:type=Engine");
        objectList.add(StrUtil.format("Tomcat:type=GlobalRequestProcessor,name=\"http-nio-{}\"", tomcatPort));
        objectList.add("Tomcat:type=ProtocolHandler,port=" + tomcatPort);
        objectList.add("Tomcat:type=Server");
        objectList.add("Tomcat:type=StringCache");
        objectList.add(StrUtil.format("Tomcat:type=ThreadPool,name=\"http-nio-{}\"", tomcatPort));
        objectList.add(StrUtil.format("Tomcat:type=ThreadPool,name=\"http-nio-{}\",subType=SocketProperties", tomcatPort));
        objectList.add("java.lang:type=ClassLoading");
        objectList.add("java.lang:type=Compilation");
        objectList.add("java.lang:type=OperatingSystem");
        objectList.add("java.lang:type=Runtime");
        objectList.add("java.lang:type=Threading");
        objectList.add("java.nio:type=BufferPool,name=direct");
        objectList.add("java.nio:type=BufferPool,name=mapped");

        for (String object : objectList) {
            StaticLog.info("{} => {} 开始采集", ip, object);

            Map<String, String> resultMap = MapUtil.newHashMap();
            JMXConnector connector = null;

            try {
                // 处理当前的URL
                String currUrl = StrUtil.format("service:jmx:rmi:///jndi/rmi://{}:{}/jmxrmi", ip, jmxPort);
                JMXServiceURL serviceURL = new JMXServiceURL(currUrl);

                connector = JMXConnectorFactory.connect(serviceURL);
                MBeanServerConnection mbsc = connector.getMBeanServerConnection();

                ObjectName objectName = new ObjectName(object);
                MBeanAttributeInfo[] attributes = mbsc.getMBeanInfo(objectName).getAttributes();

                for (MBeanAttributeInfo attribute : attributes) {
                    String name = attribute.getName();
                    try {
                        Object valueObject = mbsc.getAttribute(objectName, name);
                        resultMap.put(name, ObjectUtil.isNull(valueObject) ? "" : valueObject.toString());
                    } catch (Exception e) {
                        resultMap.put(name, "");
                    }
                }
            } finally {
                if (ObjectUtil.isNotNull(connector)) {
                    connector.close();
                }
            }

            StaticLog.info("{} => {} 回显 => {}", ip, object, JSONUtil.toJsonStr(resultMap));
            resultList.add(StrUtil.format("{} => {} 回显 => {}", ip, object, JSONUtil.toJsonStr(resultMap)));
            StaticLog.info("{} => {} 采集结束", ip, object);
        }



        // 开始收集springboot封装的接口
        StaticLog.info("{} 开始收集springboot封装的接口。。。", ip);

        // 处理当前的URL
        String currUrl = StrUtil.format("service:jmx:rmi:///jndi/rmi://{}:{}/jmxrmi", ip, jmxPort);
        JMXServiceURL serviceURL = new JMXServiceURL(currUrl);

        JMXConnector connector = JMXConnectorFactory.connect(serviceURL);
        MBeanServerConnection mbsc = connector.getMBeanServerConnection();

        // 构造ObjectName，指定要查询的MBean
        ObjectName objectName = new ObjectName("org.springframework.boot:type=Endpoint,name=Metrics");

        // 调用listNames()方法
        Object listNames = mbsc.invoke(objectName, "listNames", new Object[]{}, new String[]{});
        StaticLog.info("{} 调用listNames()结果 => {}", ip, listNames.toString());
        resultList.add(StrUtil.format("{} 调用listNames()结果 => {}", ip, listNames.toString()));

        String listName = listNames.toString();
        List<String> split = StrUtil.split(StrUtil.removeAll(StrUtil.removeAll(listName, "{names=["), "]}"), ", ");

        for (String metric : split) {
            ObjectName objectName1 = new ObjectName("org.springframework.boot:type=Endpoint,name=Metrics");
            Object value = mbsc.invoke(objectName1, "metric", new Object[]{metric}, new String[]{String.class.getName()});
            StaticLog.info("{} 调用metric() {} 结果 => {}", ip, metric, value.toString());
            resultList.add(StrUtil.format("{} 调用metric() {} 结果 => {}", ip, metric, value.toString()));
        }

        StaticLog.info("{} 调用listNames()结束。。。", ip);

        StaticLog.info("{} 开始收集springboot封装的httpTrace。。。", ip);

        ObjectName objectName2 = new ObjectName("org.springframework.boot:type=Endpoint,name=Httptrace");
        Object traces = mbsc.invoke(objectName2, "traces", new Object[]{}, new String[]{});

        StaticLog.info("{} httpTrace收集结果 => {}", ip, traces.toString());
        resultList.add(StrUtil.format("{} httpTrace收集结果 => {}", ip, traces.toString()));

        connector.close();
        return resultList;
    }


}
